/*
 * @Author: January
 * @Date: 2022-01-03 20:21:13
 */

#ifndef __CIPHER_ALGS_H__
#define __CIPHER_ALGS_H__

#include <libecc/lib_ecc_config.h>
#include <libecc/lib_ecc_types.h>
#ifndef EXTERNAL_HEADER
#include "../words/words.h"
#include "../utils/utils.h"
#endif
#ifdef WITH_CIPHER_AES_CBC
#include "aes.h"
#endif
#ifdef WITH_CIPHER_SM4_CBC
#include "sm4.h"
#endif

#define MAX_CIPHER_BLOCK_SIZE 16

// 通用的加密上下文对象
typedef union {
#ifdef WITH_CIPHER_AES_CBC
	aes_context aes_cbc;
#endif
#ifdef WITH_CIPHER_AES_CTR
	aes_context aes_ctr;
#endif
#ifdef WITH_CIPHER_SM4_CBC
    sm4_context sm4_cbc;
#endif
#ifdef WITH_CIPHER_SM4_CTR
    sm4_context sm4_ctr;
#endif
} cipher_context;


#define CIPHER_MAPPING_SANITY_CHECK(A)			\
	MUST_HAVE(((A) != NULL) && 			\
		  ((A)->name != NULL) &&		\
		  ((A)->enc_init != NULL) &&		\
		  ((A)->dec_init != NULL) &&	\
		  ((A)->enc_update != NULL) &&	\
		  ((A)->dec_update != NULL) &&	\
		  ((A)->enc_finalize != NULL) &&	\
		  ((A)->dec_finalize != NULL)
/**
 * 定义接口
 */
typedef int (*_cipher_func_enc_init) (cipher_context * ctx, const u8* iv, int iv_len, const u8* key, int key_len);
typedef void (*_cipher_func_enc) (cipher_context * ctx,
                                  const unsigned char *in, u32 inlen, unsigned char* out);
typedef void (*_cipher_func_enc_finalize) (cipher_context * ctx);
typedef int (*_cipher_func_dec_init) (cipher_context * ctx, const u8* iv, int iv_len, const u8* key, int key_len);
typedef void (*_cipher_func_dec) (cipher_context * ctx,
                                  const unsigned char *in, u32 inlen, unsigned char* out);
typedef void (*_cipher_func_dec_finalize) (cipher_context * ctx);

/*
 * All the cipher algorithms we support are abstracted using the following
 * structure (and following map) which provides for each cipher alg its
 * digest size, its block size and the associated scattered function.
 */
typedef struct {
	cipher_alg_type type;
	const char *name;
	u8 block_size;
	_cipher_func_enc_init enc_init;
	_cipher_func_enc enc;
	_cipher_func_enc_finalize enc_finalize;
    _cipher_func_dec_init dec_init;
	_cipher_func_dec dec;
	_cipher_func_dec_finalize dec_finalize;
} cipher_mapping;

const cipher_mapping *get_cipher_by_name(const char *cipher_name);
const cipher_mapping *get_cipher_by_type(cipher_alg_type cipher_type);
 #endif /* __CIPHER_ALGS_H__ */
